package com.echat.serviceapigateway.security.tool;

import com.echat.serviceapigateway.security.constant.Constants;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by chenmohan on 2018/09/18
 *
 * @description 仿照Echat项目的权限码功能实现的工具类
 */
public class AuthCodeUtil {

    public static final int INTERVAL = 64;

    /**
     * 一个组包含64个权限id
     */
    public static final int supportMaxAuthIdGroup = 5;

    /**
     * 根据传入的权限id数组压缩生成权限码
     *
     * @param authIds
     * @return
     */
    public static String genAuthCode(Long[] authIds) {
        if(authIds == null || authIds.length == 0){
            return Constants.EMPTY_AUTH_CODE;
        }
        int col = 0;
        long bitIndex = 0;
        long[] bitMap = new long[supportMaxAuthIdGroup];

        for (long id : authIds) {
            col = (int) (id / INTERVAL);
            bitIndex = id % INTERVAL;
            bitMap[col] += 1 << bitIndex;
        }
        String rawAuthCode = Arrays.toString(bitMap);
        return rawAuthCode.substring(1, rawAuthCode.length() - 1);
    }

    /**
     * 根据传入的权限id数组压缩生成权限码
     *
     * @param authIds
     * @return
     */
    public static String genAuthCode(List<Long> authIds) {
        if(authIds == null || authIds.size() == 0){
            return Constants.EMPTY_AUTH_CODE;
        }
        int col = 0;
        long bitIndex = 0;
        long[] bitMap = new long[supportMaxAuthIdGroup];

        for (long id : authIds) {
            col = (int) (id / INTERVAL);
            bitIndex = id % INTERVAL;
            bitMap[col] += 1 << bitIndex;
        }
        String rawAuthCode = Arrays.toString(bitMap);
        return rawAuthCode.substring(1, rawAuthCode.length() - 1);
    }

    public static String getAuthCodeListByIds(String ids) {
        if(StringUtils.isEmpty(ids)){
            return Constants.EMPTY_AUTH_CODE;
        }
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(e -> Long.valueOf(e.trim()))
                .collect(
                        Collectors.toList());
         return genAuthCode(idList);
    }

    /**
     * 将权限码转换成权限idList
     *
     * @param authCode 比如:"9, 0, 0, 0, 0"
     * @return
     */
    public static List<Long> getAuthIdList(String authCode) {
        List<Long> ids = new ArrayList<>();
        String[] authArray = authCode.split(",");
        StringBuilder sb = new StringBuilder();
        for (int i = authArray.length - 1; i >= 0; --i) {
            sb.append(Long.toBinaryString(Long.valueOf(authArray[i].trim())));
            if (i > 0) {
                sb.append(",");
            }
        }
        String authBinaryCode = sb.reverse().toString();
        int currentId = 0;
        int col = 0;
        for (int i = 0; i < authBinaryCode.length(); ++i) {
            switch (authBinaryCode.charAt(i)) {
                case '1':
                    ids.add((long) currentId + col * INTERVAL);
                    break;
                case ',':
                    currentId = 0;
                    col++;
                    break;
                default:
            }
            currentId++;
        }
        return ids;
    }

    public static boolean check(String authCode, long needChcekId) {
        int belongCol = (int) (needChcekId / INTERVAL);
        long bitIndex = needChcekId % INTERVAL;
        Long authCodeByCol = Long.valueOf(authCode.split(",")[belongCol]);
        return (authCodeByCol & 1 << bitIndex) > 0;
    }

    private static boolean getBit(int num, int i) {
        return ((num & (1 << i)) != 0);//true 表示第i位为1,否则为0
    }

    // 1000 0000 ,0
    // 0,0000 0001
    public static void main(String[] args) {

        System.out.println(getAuthCodeListByIds("1"));

        System.out.println("==========================");

        String authCode = genAuthCode(new Long[]{1L});

        System.err.println(authCode);

        getAuthIdList(authCode).forEach(System.out::println);

    }


}
